package com.dap.utils;

import java.math.BigDecimal;
import java.text.ParseException;

/**
 * 营业时间工具类
 * Created by wangmin on 2019/6/20.
 */
public abstract class BusinessHoursUtils {
    public static final BusinessHours ALL_DAY = new BusinessHours(new HourAndMinute(0,0), new HourAndMinute(24,0));

    private static final int MAX_HOUR_MINUTE_INT = 24*60;
    public static class HourAndMinute implements Comparable<HourAndMinute> {
        private final int hour;
        private final int minute;

        public HourAndMinute(int hour, int minute) {
            this.hour = hour;
            this.minute = minute;
        }

        public int getHour() {
            return hour;
        }
        public int getMinute() {
            return minute;
        }

        public int toInt() {
            return hour*60 + minute;
        }
        @Override
        public String toString() {
            return hour + ":" + minute;
        }
        @Override
        public int compareTo(HourAndMinute other) {
            int cmp = this.toInt() - other.toInt();
            if (cmp > 0) {
                return 1;
            } else if (cmp < 0) {
                return -1;
            } else {
                return 0;
            }
        }
    }
    public static class BusinessHours {
        private final HourAndMinute startTime;
        private final HourAndMinute endTime;
        private final ContinuousRange continuousRange;

        private static ContinuousRange generateContinuousRange(HourAndMinute startTime, HourAndMinute endTime) {
            int start = startTime.toInt();
            int end = endTime.toInt();

            ContinuousRange continuousRange = new ContinuousRange();
            if (start < end) {
                continuousRange.addBlock(new BigDecimal(start), new BigDecimal(end));
            } else if (end < start) {
                continuousRange.addBlock(BigDecimal.ZERO, new BigDecimal(end));
                continuousRange.addBlock(new BigDecimal(start), new BigDecimal(MAX_HOUR_MINUTE_INT));
            }
            return continuousRange;
        }

        public BusinessHours(HourAndMinute startTime, HourAndMinute endTime) {
            this.startTime = startTime;
            this.endTime = endTime;
            this.continuousRange = generateContinuousRange(startTime, endTime);
        }

        public HourAndMinute getStartTime() {
            return startTime;
        }
        public HourAndMinute getEndTime() {
            return endTime;
        }
        public ContinuousRange getContinuousRange() {
            return continuousRange;
        }
    }


    /**
     * 使用
     * 23:30
     * 这种格式的表示时间
     * */
    public static HourAndMinute parseHourAndMinute(String timeStr) throws ParseException {
        if (null == timeStr || timeStr.length() != 5) {
            throw new ParseException("invalid hour minute:["+timeStr+"]", 0);
        }

        if (timeStr.charAt(0) != '0' && timeStr.charAt(0) != '1' && timeStr.charAt(0) != '2') {
            throw new ParseException("invalid hour minute:["+timeStr+"]", 0);
        }
        if (timeStr.charAt(1) < '0' || '9' < timeStr.charAt(1)) {
            throw new ParseException("invalid hour minute:["+timeStr+"]", 1);
        }
        int hour = 10 * (timeStr.charAt(0)-'0') + (timeStr.charAt(1)-'0');
        if (hour == 24) {
            hour = 0;
        }
        if (hour < 0 || hour >= 24) {
            throw new ParseException("invalid hour minute:["+timeStr+"]", 0);
        }

        if (timeStr.charAt(3) < '0' || '5' < timeStr.charAt(3)) {
            throw new ParseException("invalid hour minute:["+timeStr+"]", 3);
        }
        if (timeStr.charAt(4) < '0' || '9' < timeStr.charAt(4)) {
            throw new ParseException("invalid hour minute:["+timeStr+"]", 4);
        }
        int minute = 10 * (timeStr.charAt(3)-'0') + (timeStr.charAt(4)-'0');
        if (minute < 0 || minute >= 60) {
            throw new ParseException("invalid hour minute:["+timeStr+"]", 3);
        }

        return new HourAndMinute(hour, minute);
    }

    public static BusinessHours parseBusinessHours(String startTimeStr, String endTimeStr) throws ParseException {
        final HourAndMinute startTime = parseHourAndMinute(startTimeStr);
        final HourAndMinute endTime = parseHourAndMinute(endTimeStr);
        return new BusinessHours(startTime, endTime);
    }


    /**
     * 检查checkBusinessHours是否在allowBusinessHours之内
     * */
    public static boolean isWithinTime(BusinessHours allowBusinessHours, BusinessHours checkBusinessHours) {
        ContinuousRange allowContinuousRange = allowBusinessHours.getContinuousRange();
        ContinuousRange checkContinuousRange = checkBusinessHours.getContinuousRange();
        return allowContinuousRange.isParent(checkContinuousRange);
    }
    /**
     * 检查checkHourAndMinute是否在allowBusinessHours之内
     * */
    public static boolean isWithinTime(BusinessHours allowBusinessHours, HourAndMinute checkHourAndMinute) {
        ContinuousRange allowContinuousRange = allowBusinessHours.getContinuousRange();
        BigDecimal bigDecimal = new BigDecimal(checkHourAndMinute.toInt());

        return allowContinuousRange.getBlockIndexByStartAddressCloseClose(bigDecimal) >= 0;
    }

    public static void main(String[] args) throws ParseException {
        BusinessHours allowBusinessHours = parseBusinessHours("10:02", "03:57");
        BusinessHours checkBusinessHours = parseBusinessHours("10:01", "03:58");

        boolean isWithin = isWithinTime(allowBusinessHours, checkBusinessHours);
        System.out.println("isWithin=" + isWithin);
    }
}
